<template>
  <Dialog
    v-model="dialogVisible"
    :title="title"
    width="1000px"
    :close-on-click-modal="false"
    @close="handleClose"
    append-to-body
    class="advanced-filter-dialog"
  >
    <!-- 包含条件部分 -->
    <div class="filter-section">
      <div class="section-header">
        <div class="header-left">
          <span class="section-title">包含条件</span>
        </div>
        <div class="header-right">
          <e-button size="small" plain @click="handlePaste('includeRows')" :icon="CopyDocument">
            从剪贴板粘贴
          </e-button>
          <e-button plain @click="addIncludeRow" :icon="Plus">添加</e-button>
        </div>
      </div>
      <div v-for="(row, rowIndex) in includeRows" :key="'include-' + rowIndex" class="filter-row">
        <el-select
          v-model="row.logicType"
          class="operator-select"
          :class="{ 'el-visible': !rowIndex }"
        >
          <el-option label="且" value="and" />
          <el-option label="或" value="or" />
        </el-select>
        <el-select v-model="row.operator" class="operator-select">
          <el-option
            v-for="(item, index) in operatorSelect"
            :key="index"
            :label="item.label"
            :value="item.value"
          />
        </el-select>

        <template v-if="filterConfig.type == 'select'">
          <el-select
            v-model="row.value"
            class="value-select"
            :placeholder="getPlaceholder(row.operator)"
            @change="validateSelect(row)"
          >
            <el-option
              v-for="item in filterConfig.options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </template>
        <template v-else-if="filterConfig.type == 'remoteSelect'">
          <e-remote-select
            v-model="row.value"
            :placeholder="filterConfig.placeholder"
            :initOptions="filterConfig.options"
            :showFiled="filterConfig.showFiled"
            :query-api="filterConfig.queryApi"
            :type="filterConfig.remoteType"
            clearable
            @update:value-model="filterConfig.handleUpdateValueModel"
            v-bind="filterConfig.attrs"
            :isSearch="false"
          />
        </template>
        <template v-else-if="filterConfig.type === 'date'">
          <el-date-picker
            v-model="row.value"
            class="value-input"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            :placeholder="getPlaceholder(row.operator)"
            @change="validateInput(row)"
          />
        </template>
        <template v-else-if="filterConfig.type === 'dateRange'">
          <el-date-picker
            v-model="row.value"
            class="value-input"
            type="daterange"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            range-separator="To"
            start-placeholder="Start date"
            end-placeholder="End date"
            :placeholder="getPlaceholder(row.operator)"
            @change="validateInput(row)"
          />
        </template>
        <template v-else-if="row.operator === 'range' || row.operator === 'not_range'">
          <el-input
            v-model="row.value1"
            class="value-input"
            placeholder="最小值"
            @change="validateInput(row)"
          />
          <span>至</span>
          <el-input
            v-model="row.value2"
            class="value-input"
            placeholder="最大值"
            @change="validateInput(row)"
          />
        </template>
        <template v-else>
          <el-input
            v-model="row.value"
            class="value-input"
            :placeholder="getPlaceholder(row.operator)"
            @change="validateInput(row)"
          />
        </template>
        <e-button @click="removeIncludeRow(rowIndex)" :icon="Delete">删除</e-button>
      </div>
    </div>

    <!-- 排除条件部分 -->
    <div class="filter-section">
      <div class="section-header">
        <div class="header-left">
          <span class="section-title">排除条件</span>
        </div>
        <div class="header-right">
          <e-button plain @click="handlePaste('excludeRows')" :icon="CopyDocument">
            从剪贴板粘贴
          </e-button>
          <e-button plain @click="addExcludeRow" :icon="Plus">添加</e-button>
        </div>
      </div>
      <div v-for="(row, rowIndex) in excludeRows" :key="'exclude-' + rowIndex" class="filter-row">
        <el-select
          v-model="row.logicType"
          class="operator-select"
          :class="{ 'el-visible': !rowIndex }"
        >
          <el-option label="且" value="and" />
          <el-option label="或" value="or" />
        </el-select>
        <el-select v-model="row.operator" class="operator-select">
          <el-option
            v-for="(item, index) in operatorSelect"
            :key="index"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <template v-if="filterConfig.type == 'select'">
          <el-select
            v-model="row.value"
            class="value-select"
            :placeholder="getPlaceholder(row.operator)"
            @change="validateSelect(row)"
          >
            <el-option
              v-for="item in filterConfig.options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </template>
        <template v-else-if="filterConfig.type == 'remoteSelect'">
          <e-remote-select
            v-model="row.value"
            :placeholder="filterConfig.placeholder"
            :initOptions="filterConfig.options"
            :showFiled="filterConfig.showFiled"
            :query-api="filterConfig.queryApi"
            :type="filterConfig.remoteType"
            clearable
            @update:value-model="filterConfig.handleUpdateValueModel"
            v-bind="filterConfig.attrs"
            :isSearch="false"
          />
        </template>
        <template v-else-if="filterConfig.type === 'date'">
          <el-date-picker
            v-model="row.value"
            class="value-input"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            :placeholder="getPlaceholder(row.operator)"
            @change="validateInput(row)"
          />
        </template>
        <template v-else-if="filterConfig.type === 'dateRange'">
          <el-date-picker
            v-model="row.value"
            class="value-input"
            type="daterange"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            range-separator="To"
            start-placeholder="Start date"
            end-placeholder="End date"
            :placeholder="getPlaceholder(row.operator)"
            @change="validateInput(row)"
          />
        </template>
        <template v-else-if="row.operator === 'range' || row.operator === 'not_range'">
          <el-input
            v-model="row.value1"
            class="value-input"
            placeholder="最小值"
            @change="validateInput(row)"
          />
          <span>至</span>
          <el-input
            v-model="row.value2"
            class="value-input"
            placeholder="最大值"
            @change="validateInput(row)"
          />
        </template>
        <template v-else>
          <el-input
            v-model="row.value"
            class="value-input"
            :placeholder="getPlaceholder(row.operator)"
            @change="validateInput(row)"
          />
        </template>
        <e-button @click="removeExcludeRow(rowIndex)" :icon="Delete">删除</e-button>
      </div>
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="handleClose">取消</el-button>
        <el-button type="primary" @click="handleConfirm">确认</el-button>
      </span>
    </template>
  </Dialog>
</template>

<script setup>
  import { ref, defineExpose, nextTick,computed  } from 'vue'
  import { ElMessage } from 'element-plus'
  import { Delete, Plus, CopyDocument } from '@element-plus/icons-vue'
  import _ from 'lodash-es'
  // 所有操作符
  const operatorAll = [
    { label: '等于', value: 'eq' },
    { label: '不等于', value: 'neq' },
    { label: '大于', value: 'gt' },
    { label: '大于或等于', value: 'gte' },
    { label: '小于', value: 'lt' },
    { label: '小于或等于', value: 'lte' },
    { label: '范围', value: 'range' },
    { label: '范围外', value: 'not_range' },
    { label: '模糊匹配', value: 'like' }
  ]

  const props = defineProps({
    field: {
      type: String,
      required: true
    },
    title: {
      type: String
    },
    filterConfig: {
      type: Object
    },
    searchValue: {
      type: [String, Number],
      default: ''
    }
  })

  // 根据类型过滤操作符
  const operatorSelect = computed(() => {
    if (props.filterConfig?.type === 'remoteSelect') {
      return operatorAll.filter((item) => ['eq', 'neq'].includes(item.value))
    } else {
      return operatorAll
    }
  })

  // 触发事件
  const emit = defineEmits(['filter-change', 'clear-filter'])

  // 弹窗是否显示
  const dialogVisible = ref(false)

  // 分别定义包含和排除条件数组
  const includeRows = ref([])
  const excludeRows = ref([])

  // 创建新行
  function createNewRow() {
    return {
      logicType: 'or',
      operator: 'eq',
      value: '',
      value1: null,
      value2: null,
      isValid: true
    }
  }

  // 添加包含条件行
  const addIncludeRow = () => {
    includeRows.value.push(createNewRow())
  }

  // 添加排除条件行
  const addExcludeRow = () => {
    excludeRows.value.push(createNewRow())
  }

  // 删除包含条件行
  const removeIncludeRow = (index) => {
    includeRows.value.splice(index, 1)
  }

  // 删除排除条件行
  const removeExcludeRow = (index) => {
    excludeRows.value.splice(index, 1)
  }

  // 获取输入框提示文本
  const getPlaceholder = (operator) => {
    const placeholders = {
      eq: '输入等于值',
      neq: '输入不等于值',
      gt: '输入大于值',
      gte: '输入大于或等于值',
      lt: '输入小于值',
      lte: '输入小于或等于值',
      range: '输入范围值',
      not_range: '输入排除范围值',
      like: '输入模糊匹配值'
    }
    return placeholders[operator] || '请输入值'
  }

  // 验证输入
  const validateInput = (row) => {
    if (row.operator === 'range' || row.operator === 'not_range') {
      if (row.value1 !== null && row.value2 !== null && row.value1 > row.value2) {
        ElMessage.error('范围值无效：最小值不能大于最大值')
        row.isValid = false
        return
      }
    }

    row.isValid = true
    return row
  }

  // 验证下拉
  const validateSelect = (row) => {
    if (row.operator === 'range' || row.operator === 'not_range') {
      if (row.value1 !== null && row.value2 !== null && row.value1 > row.value2) {
        ElMessage.error('范围值无效：最小值不能大于最大值')
        row.isValid = false
        return
      }
    }

    row.isValid = true
    return row
  }

  // 处理剪贴板粘贴
  const handlePaste = async (type) => {
    try {
      const text = await navigator.clipboard.readText()
      const values = text.split('\n').filter((v) => v.trim())

      values.forEach((value) => {
        if (type === 'includeRows') {
          includeRows.value.push({
            ...createNewRow(),
            value: value.trim()
          })
        } else {
          excludeRows.value.push({
            ...createNewRow(),
            value: value.trim()
          })
        }
      })
    } catch (err) {
      ElMessage.error('无法访问剪贴板')
    }
  }

  // 清除筛选条件
  const clearFilter = () => {
    // 重置筛选条件
    includeRows.value = []
    excludeRows.value = []
  }
  // 构建返回数据
  const getFilterConditions = () => {
    includeRows.value = includeRows.value.filter((row) => row.value || row.value1 || row.value2)
    excludeRows.value = excludeRows.value.filter((row) => row.value || row.value1 || row.value2)
    const filterConditions = {
      // 包含条件
      include: includeRows.value.map((row) => ({
        logicType: row.logicType,
        operator: row.operator,
        value: ['range', 'not_range'].includes(row.operator)
          ? [row.value1, row.value2].join('~')
          : row.value
      })),
      // 排除条件
      exclude: excludeRows.value.map((row) => ({
        logicType: row.logicType,
        operator: row.operator,
        value: ['range', 'not_range'].includes(row.operator)
          ? [row.value1, row.value2].join('~')
          : row.value
      })),
      // 字段
      field: props.field
    }
    return filterConditions
  }
  // 是否点击确认按钮
  const isConfirm = ref(false)
  // 确认时 构建筛选条件数据
  const handleConfirm = () => {
    isConfirm.value = true
    // 验证所有输入是否有效
    const isAllValid = [...includeRows.value, ...excludeRows.value].every((row) => row.isValid)
    if (!isAllValid) {
      ElMessage.error('存在无效的筛选条件，请检查')
      return
    }

    emit('filter-change', getFilterConditions(), true)
    dialogVisible.value = false
  }

  // 关闭弹窗/取消按钮: 恢复初始数据,将包含条件中第一条非空数据回填到输入框
  const handleClose = () => {
    // 如果点击确认按钮，则不恢复初始数据
    if (isConfirm.value) {
      return
    }
    // 恢复初始数据
    includeRows.value = _.cloneDeep(includeRowsCopy.value)  
    excludeRows.value = _.cloneDeep(excludeRowsCopy.value) 

    emit('filter-change', getFilterConditions(), false)
    dialogVisible.value = false
  }

  // 复制数据
  const includeRowsCopy = ref({})
  const excludeRowsCopy = ref({})
  // 打开弹窗
  /* 打开弹窗时进行判断
    1.当props.searchValue存在时
      如果searchValue包含~,且包含条件中第一个元素operator是range/not_range时，将searchValue用~分割分别赋值给value1/value2
      如果searchValue不包含~,且包含条件中第一个元素operator是range/not_range时，将searchValue赋值给value，设置operator为eq
      如果searchValue不包含~，将searchValue赋值给value，不改变operator
    2.当props.searchValue不存在时
      如果包含条件数组中数据量大于1，则删除第一条数据
      否则，将包含条件数组中第一个元素的value赋值给空,设置operator为eq
  */
  /* include: 包含条件标识
    exclude: 排除条件标识
 */
  const openDialog = (prop, include, exclude) => {
    dialogVisible.value = true
    isConfirm.value = false
    // 当searchValue存在时的处理
    if (exclude) {
      excludeRows.value = adjustFilterConditions(props.searchValue, excludeRows.value)
    } else {
      includeRows.value = adjustFilterConditions(props.searchValue, includeRows.value)
    }

    // 确保数据已经更新
    nextTick(() => {
      // 复制数据
      includeRowsCopy.value = _.cloneDeep(includeRows.value) 
      excludeRowsCopy.value = _.cloneDeep(excludeRows.value) 
    })
  }

  // 打开弹窗时，回填包含/排除条件
  const adjustFilterConditions = (value, rows) => {
    console.log('filterConfig=>', props.filterConfig)
    if (rows.length > 0) {
      if (value) {
        const isRangeOperator = ['range', 'not_range'].includes(rows[0].operator)
        if (value.toString().includes('~') && isRangeOperator) {
          const [value1, value2] = value.split('~')
          rows[0].value1 = value1
          rows[0].value2 = value2
          rows[0].value = null
        } else if (isRangeOperator) {
          rows[0].value = value
          rows[0].operator = 'eq'
          rows[0].value1 = null
          rows[0].value2 = null
        } else if (Array.isArray(value)) {
          rows = []
          value.forEach((item) => {
            rows.push({
              logicType: 'or',
              value: item,
              operator: 'eq',
              value1: null,
              value2: null,
              isValid: true
            })
          })
        } else {
          rows[0].value = value
        }
      } else {
        rows.splice(0, 1)
      }
    } else {
      if (value) {
        // 否则新增一条数据
        rows.push({
          operator: props.filterConfig.defaultOperator || 'eq',
          value: value,
          value1: null,
          value2: null,
          isValid: true
        })
      }
    }
    return rows
  }
  // 设置包含条件
  const setIncludeRows = (include) => {
    includeRows.value = include
  }
  // 设置排除条件
  const setExcludeRows = (exclude) => {
    excludeRows.value = exclude
  }
  // 获取包含条件
  const getIncludeRows = () => {
    return includeRows.value
  }
  // 获取排除条件
  const getExcludeRows = () => {
    return excludeRows.value
  }

  // 暴露方法给父组件
  defineExpose({
    openDialog,
    clearFilter,
    setIncludeRows,
    setExcludeRows,
    getIncludeRows,
    getExcludeRows
  })
</script>

<style scoped>
  .filter-section {
    margin-bottom: 20px;
    /* padding: 20px; */
    /* background: #fff; */
    /* border-radius: 4px; */
  }

  .section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
  }

  .header-left {
    display: flex;
    align-items: center;
    gap: 12px;
  }

  .section-title {
    font-size: 16px;
    /* font-weight: 600; */
    color: #1d2129;
  }

  .filter-row {
    display: flex;
    align-items: center;
    margin-bottom: 12px;
    gap: 12px;
  }

  .operator-select {
    width: 140px;
  }

  .value-input,
  .value-select {
    flex: 1;
    min-width: 200px;
  }

  :deep(.el-input-number) {
    width: 120px;
  }

  .dialog-footer {
    width: 100%;
    display: flex;
    justify-content: flex-end;
    gap: 12px;
  }

  .el-visible {
    visibility: hidden;
  }
</style>
<style>
  .advanced-filter-dialog {
    padding: 0 !important;
    .el-dialog__body {
      padding: 15px !important;
    }
  }
</style>
